#include "StdAfx.h"
#include "LinkED_UDP.h"
#include "LinkED_PCDlg.h"
#include "LinkED_GloablDefines.h"
#include "LinkED_DataQuene.h"


CLinkED_UDP::CLinkED_UDP(void)
{
}


CLinkED_UDP::~CLinkED_UDP(void)
{

}

bool CLinkED_UDP::Init( CMainDlg* mainpage, std::string& ip, unsigned short port )
{
    m_MainPage = mainpage;

    if (!IntialUDPBind(ip, port))
    {
        return false;
    }

    if (!StartReceiveThread())
    {
        Fini();
        return false;
    }

    return true;
}

void CLinkED_UDP::Fini()
{
    closesocket(m_Socket);
    StopReceiveThread();
}

bool CLinkED_UDP::IntialUDPBind(std::string& ip, unsigned short port)
{
    m_Socket = socket(AF_INET, SOCK_DGRAM, 0);

    if (INVALID_SOCKET == m_Socket)
    {
        return false;
    }

    SOCKADDR_IN addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    //addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
    
    if (SOCKET_ERROR == bind(m_Socket,(sockaddr*)&addr, sizeof(addr)))
    {
        return false;
    }

    return true;
}

bool CLinkED_UDP::StartReceiveThread()
{
    m_ReceiveThreadHandle = CreateThread(NULL, NULL, UDPReceiveThreadFunc,
        this, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);

    if (NULL == m_ReceiveThreadHandle)
    {
        return false;
    }

    return true;
}

void CLinkED_UDP::StopReceiveThread()
{
    if (m_ReceiveThreadHandle != NULL)
    {
        WaitForSingleObject(m_ReceiveThreadHandle, INFINITE);
        CloseHandle(m_ReceiveThreadHandle);
        m_ReceiveThreadHandle = NULL;
    }
}

DWORD WINAPI CLinkED_UDP::UDPReceiveThreadFunc( LPVOID userdata )
{
    CLinkED_UDP* pThis = (CLinkED_UDP*)userdata;

    ScreenPos buffer;
    SOCKADDR_IN clientaddr;
    int len = sizeof(clientaddr);
    int result = 0;

    do
    {
        result = recvfrom(pThis->m_Socket, (char*)&buffer, sizeof(ScreenPos), 0, 
            (sockaddr*)&clientaddr, &len);

        if (result > 0)
        {
            // process data here
            TRACE("Sock: %s, x: %d, y:%d, msg_type: %d \n", inet_ntoa(clientaddr.sin_addr), buffer.x, buffer.y, buffer.msg_type);
            CDataQuene::GetInstance()->PushMouseMoveInput(&buffer);
        }
        else if (result == 0)
        {
            // connection is closing
        }
        else
        {
            // connection error.
            break;
        }

    }while(true);

    return 0;
}




